package com.nexgo.payment.databases.mapper;

import android.text.TextUtils;

import com.nexgo.common.ByteUtils;
import com.nexgo.data.entity.RecvData;
import com.nexgo.data.entity.SendData;
import com.nexgo.data.json.JsonRecData;
import com.nexgo.data.json.JsonSendData;
import com.nexgo.data.json.JsonTools;
import com.nexgo.data.json.bean.JsonBody;
import com.nexgo.payment.constrant.OfflineState;
import com.nexgo.payment.constrant.PreferencesConstants;
import com.nexgo.payment.constrant.SysConstant;
import com.nexgo.payment.databases.DataSource;
import com.nexgo.payment.databases.TransRecord;
import com.nexgo.payment.entity.TransData;
import com.nexgo.payment.trans.AbsOnlinePresenter;
import com.nexgo.payment.util.StringUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

import java8.util.Optional;

/**
 * Created by xiaox on 2017/8/11.
 */

/**
 * 交易记录转换
 */
public class TransRecordMapper {

    private final Logger mLog = LoggerFactory.getLogger(AbsOnlinePresenter.class.getSimpleName());
    /**
     * 从交易采集数据以及发送包组数据库记录
     *
     * @param transData  交易采集数据
     * @param sendData   发送包数据
     * @param repository
     * @return 交易记录
     */
    public TransRecord transform(TransData transData, SendData sendData, DataSource repository) {
        //能从发送包取的，都从发送包取，数据与后台一致
        TransRecord transRecord = new TransRecord();
        //来自发送包
        //主帐号
        transRecord.setPan(sendData.getPan());
        //金额
        transRecord.setAmount(sendData.getAmount());
        //凭证号
        transRecord.setTraceNum(sendData.getTraceNum());
        //有效期
        transRecord.setExpDate(sendData.getExpDate());
        //用卡方式
        transRecord.setEntryMode(sendData.getEntryMode());
        //卡序列号
        transRecord.setCsn(sendData.getCsn());
        //授权码
        transRecord.setAuthCode(sendData.getAuthCode());
        //系统参考号
        transRecord.setRefNum(sendData.getRefNum());
        //终端号
        transRecord.setTerminalId(sendData.getTerminalId());
        //商户号
        transRecord.setMerchantId(sendData.getMerchantId());
        //交易时间
        transRecord.setTime(StringUtils.firstNonEmpty(sendData.getTime(), new SimpleDateFormat("HHmmss", SysConstant.LOCALE).format(new Date())));
        //交易日期
        transRecord.setDate(StringUtils.firstNonEmpty(sendData.getDate(), new SimpleDateFormat("MMdd", SysConstant.LOCALE).format(new Date())));
        //货币代码
        transRecord.setFundType(sendData.getFundType());
        //55域
        transRecord.setEmvTlv(sendData.getEmvTlv());
        //批次号
        Optional.ofNullable(sendData.getField60())
                .filter(s -> s.length() >= 6)
                .ifPresent(s -> transRecord.setField60(sendData.getField60()));

        Optional.ofNullable(sendData.getField62())
                .ifPresent(s -> {
                    if (s.length() >= 6) {
                        transRecord.setBatchNum(s.substring(0, 6));
                    }
                    if (s.length() >= 12) {
                        transRecord.setTraceNum(s.substring(6, 12));
                    }
                    if (s.length() >= 18) {
                        transRecord.setOrgTraceNum(s.substring(12, 18));
                    }
                });
        transRecord.setIsNotify(sendData.getMsgType().equals("0220"));
        //来自交易采集
        //支付码号（扫码相关）
        /*transRecord.setScanChannel(transData.getScanChannel());  //lr add
        transRecord.setPayCodeNo(transData.getPayCodeNo());*/
        //付款凭证码（扫码相关）
        transRecord.setPayTraceCode(transData.getTraceCode());
        //商户名称
        transRecord.setMerchantName(repository.getParamValue(PreferencesConstants.MERCHANT_NAME));
        //交易类型
        transRecord.setTransType(transData.getTransType().ordinal());
        //操作员
        Optional.ofNullable(repository.getParamValue(PreferencesConstants.CURRENT_OPERATOR_NO))
                .filter(s -> !TextUtils.isEmpty(s))
                .filter(s -> TextUtils.isDigitsOnly(s))
                .map(s -> Integer.parseInt(s))
                .ifPresentOrElse(integer -> transRecord.setOperator(integer), () -> transRecord.setOperator(1));
        //用卡方式
        if (transData.getCardMode() != null) {
            transRecord.setCardMode(transData.getCardMode().ordinal());
        }
        //原授权号
        transRecord.setOrgAuthCode(transData.getOrgAuthCode());
        //原系统参考号
        transRecord.setOrgRefNum(transData.getOrgRefNum());
        //持卡人
        transRecord.setCardHolder(getCardHolder(transData.getTk1()));
        //是否需要冲正
        transRecord.setIsNeedReversal(transData.getTransType().isReversal());
        //是否脱机交易
        transRecord.setOfflineState(transData.getOfflineState().ordinal());
        //emv交易结果数据
        transRecord.setResultTlv(transData.getResultTlv());
        //emv冲正数据
        transRecord.setReversalTlv(transData.getReversalTlv());
        //是否走了免密流程
        transRecord.setIsQpsFreePin(transData.isQpsFreePin());
        //是否走了fallback
        transRecord.setIsFallback(transData.isFallback());
        //是否走了cdcvm
        transRecord.setIsCdcvm(transData.isCdcvm());
        //免密金额
        transRecord.setQpsFreePinAmountLimit(repository.getParamValue(PreferencesConstants.QPS_LIMIT_OF_FREE_PASSWORD));
        //免签金额
        transRecord.setQpsFreeSignatureAmountLimit(repository.getParamValue(PreferencesConstants.QPS_LIMIT_OF_FREE_SIGNATURE));
        //原交易日期
        transRecord.setOrgDate(transData.getOrgDate());
        //联机的交易才要置冲正标志
        if (OfflineState.ONLINE.equals(transData.getOfflineState())) {
            transRecord.setIsNeedReversal(transData.getTransType().isReversal());
        }
        return transRecord;
    }

    /**
     * 扫码类交易从交易采集数据以及发送包组数据库记录
     *
     * @param transData  交易采集数据
     * @param sendData   发送包数据
     * @param repository
     * @return 交易记录
     */
    public TransRecord transform(TransData transData, JsonSendData sendData, DataSource repository) {

        JsonBody jsonBody = JsonTools.fromJson(sendData.getREQ_BODY().getDECRYPT(),JsonBody.class);

        //能从发送包取的，都从发送包取，数据与后台一致
        TransRecord transRecord = new TransRecord();
        //来自发送包
        //金额
        transRecord.setAmount(transData.getAmount());
        //凭证号
        mLog.debug("凭证号={}",jsonBody.getTerm_pos_no());
        transRecord.setTraceNum(jsonBody.getTerm_pos_no());

        //终端号
        transRecord.setTerminalId(jsonBody.getTerm_id());
        //商户号
        transRecord.setMerchantId(sendData.getREQ_HEAD().getMcht_id());
        //交易时间
        transRecord.setTime(sendData.getREQ_HEAD().getTerm_trans_time().substring(8,14));
        //交易日期
        transRecord.setDate(sendData.getREQ_HEAD().getTerm_trans_time().substring(4,8));
        //货币代码
        transRecord.setFundType("156");

        //批次号
        transRecord.setBatchNum(jsonBody.getTerm_batch_no());

        //来自交易采集
        //支付码号（扫码相关）
        transRecord.setScanChannel(jsonBody.getChannel());  //lr add
        transRecord.setPayCodeNo(jsonBody.getAuth_code());
        transRecord.setPayTraceCode(jsonBody.getSys_order_no());
        transRecord.setOrgBatchNum(transData.getOrgBatchNum());
        transRecord.setOrgTraceNum(transData.getOrgTraceNum());

        //商户名称
        transRecord.setMerchantName(repository.getParamValue(PreferencesConstants.MERCHANT_NAME));
        //交易类型
        transRecord.setTransType(transData.getTransType().ordinal());
        //操作员
        Optional.ofNullable(repository.getParamValue(PreferencesConstants.CURRENT_OPERATOR_NO))
                .filter(s -> !TextUtils.isEmpty(s))
                .filter(s -> TextUtils.isDigitsOnly(s))
                .map(s -> Integer.parseInt(s))
                .ifPresentOrElse(integer -> transRecord.setOperator(integer), () -> transRecord.setOperator(1));

        //是否需要冲正
        transRecord.setIsNeedReversal(transData.getTransType().isReversal());

        return transRecord;
    }

    /**
     * 更新交易记录
     *
     * @param transData   交易采集数据
     * @param recvData    接收包
     * @param transRecord 原交易数据
     * @return 交易数据
     */
    public TransRecord transform(TransData transData, RecvData recvData, TransRecord transRecord) {
        //来自发送包
        if (recvData != null) {
            //更新后台交易时间
            Optional.ofNullable(recvData.getTime()).ifPresent(s -> transRecord.setTime(s));
            //更新后台交易时期
            Optional.ofNullable(recvData.getDate()).ifPresent(s -> transRecord.setDate(s));
            //更新结算日期
            Optional.ofNullable(recvData.getSettleDate()).ifPresent(s -> transRecord.setSettleDate(s));
            //受理方标识码
            Optional.ofNullable(recvData.getAcceptCode()).ifPresent(s -> transRecord.setAcceptCode(s));
            //更新参考号
            Optional.ofNullable(recvData.getRefNum()).ifPresent(s -> transRecord.setRefNum(s));
            //更新授权码
            Optional.ofNullable(recvData.getAuthCode()).ifPresent(s -> transRecord.setAuthCode(s));
            //更新响应码
            Optional.ofNullable(recvData.getRespCode()).ifPresent(s -> transRecord.setRespCode(s));
            //更新终端号
            Optional.ofNullable(recvData.getTerminalId()).ifPresent(s -> transRecord.setTerminalId(s));
            //更新商户号
            Optional.ofNullable(recvData.getMerchantId()).ifPresent(s -> transRecord.setMerchantId(s));
            //更新收单行发卡行代号
            /*Optional.ofNullable(recvData.getAdditionalRespData())
                    .ifPresent(s -> {
                        transRecord.setIssCode(s.substring(0, 8).trim());
                        transRecord.setAcqCode(s.substring(11, 11 + 8).trim());
                    });*/
            //营销信息
//            Optional.ofNullable(recvData.getMarketInfo()).ifPresent(s -> transRecord.setMarketInfo(s));
            //余额
            Optional.ofNullable(recvData.getBalance()).ifPresent(s -> transRecord.setBalance(s));
            //更新付款凭证码（扫码相关）
/*            Optional.ofNullable(recvData.getField59())
                    .map(s -> ByteUtils.hexString2ByteArray(s))
                    .filter(bytes -> bytes != null && bytes.length != 0)
                    .map(bytes -> new String(bytes).toUpperCase())
                    .filter(s -> s.length() >= 5 && "A4".equals(s.substring(0, 2)))
                    .ifPresent(s -> transRecord.setPayTraceCode(s.substring(2 + 3).trim()));*/


//                Optional.ofNullable(recvData.getField63()).ifPresentOrElse(s ->transRecord.setIsInternational(true));
                // wzp add
                Optional.ofNullable(recvData.getField63()).ifPresentOrElse(s -> {
                //每段20个字节，转为 String 后无法区分
                try {
//                    byte[] bValue = s.getBytes(SysConstant.GBK);
                    byte[] bValue = ByteUtils.hexString2ByteArray(s);
                    if (bValue.length > 6) {
                        transRecord.setCardType(new String(Arrays.copyOfRange(bValue, 2, 2 + 10), SysConstant.GBK).trim());
//                        transRecord.setIssInfo(new String(Arrays.copyOfRange(bValue, 3, 3 + 20), SysConstant.GBK).trim());
                    }
                    if (bValue.length > 25) {
                        transRecord.setIsInternational(true);
//                        transRecord.setCardType(new String(Arrays.copyOfRange(bValue, 2, 2 + 10), SysConstant.GBK).trim());
//                        transRecord.setIssInfo(new String(Arrays.copyOfRange(bValue, 3, 3 + 20), SysConstant.GBK).trim());
                    }

                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }, () -> transRecord.setInterOrgCode("000"));
        }
        //来自交易采集
        //55域数据
        Optional.ofNullable(transData.getField55Tlv()).ifPresent(s -> transRecord.setEmvTlv(s));
        //脚本数据
        Optional.ofNullable(transData.getScriptTlv()).ifPresent(s -> transRecord.setScriptTlv(s));
        //交易结果数据
        Optional.ofNullable(transData.getResultTlv()).ifPresent(s -> transRecord.setResultTlv(s));
        //冲正原因码
        Optional.ofNullable(transData.getReversalCode()).ifPresent(s -> transRecord.setReversalCode(s));
        //是否arpc错
        transRecord.setIsArpcErr(transData.isArpcErr());
        //是否走免签
        transRecord.setIsQpsFreeSignature(transData.isQpsFreeSignature());
        //交易是否成功
        transRecord.setIsSuccess(transData.isSuccess());
        //交易是成功了，响应码为空，应该是脱机交易，响应码置为00
        if (transRecord.getIsSuccess()) {
            if (TextUtils.isEmpty(transRecord.getRespCode())) {
                transRecord.setRespCode("00");
            }
        }
        //交易成功或是无冲正原因码，则去除冲正标志
        if (transData.isSuccess() || TextUtils.isEmpty(transData.getReversalCode())) {
            transRecord.setIsNeedReversal(false);
        }
        return transRecord;
    }


    /**
     * 更新交易记录 扫码交易
     *
     * @param transData   交易采集数据
     * @param recvData    接收包
     * @param transRecord 原交易数据
     * @return 交易数据
     */
    public TransRecord transform(TransData transData, JsonRecData recvData, TransRecord transRecord) {
        JsonBody jsonBody = JsonTools.fromJson(recvData.getREQ_BODY().getDECRYPT(),JsonBody.class);

        //来自发送包
        if (recvData != null) {
            //更新后台交易时间 lr add
            if(jsonBody.getSys_trace_time() != null){
                transRecord.setTime(jsonBody.getSys_trace_time().substring(8,14));
                transRecord.setDate(jsonBody.getSys_trace_time().substring(4,8));
            }
//            Optional.ofNullable(recvData.getTime()).ifPresent(s -> transRecord.setTime(s));
            //更新后台交易时期 暂屏蔽 后台没返回 lr add
//            Optional.ofNullable(recvData.getDate()).ifPresent(s -> transRecord.setDate(s));
            //更新终端号 暂屏蔽 后台没返回 lr add
//            Optional.ofNullable(recvData.getTerminalId()).ifPresent(s -> transRecord.setTerminalId(s));
            //更新商户号
            Optional.ofNullable(recvData.getREQ_BODY().getMcht_id()).ifPresent(s -> transRecord.setMerchantId(s));

            //lr add 接收包不返回渠道和支付码,发送包存
//            transRecord.setScanChannel(transData.getScanChannel());
//            transRecord.setPayCodeNo(transData.getPayCodeNo());
            transRecord.setPayTraceCode(jsonBody.getSys_order_no());


        }
        //交易是否成功
        transRecord.setIsSuccess(transData.isSuccess());
        transRecord.setTransType(transData.getTransType().ordinal());
        //交易是成功了，响应码为空，应该是脱机交易，响应码置为00
        if (transRecord.getIsSuccess()) {
            transRecord.setRespCode("00");
        }
        //交易成功或是无冲正原因码，则去除冲正标志
        if (transData.isSuccess() || TextUtils.isEmpty(transData.getReversalCode())) {
            transRecord.setIsNeedReversal(false);
        }
        return transRecord;
    }
    /**
     * 从一磁道获取持卡人姓名
     *
     * @param tk1 一磁道
     * @return 持卡人姓名
     */
    private String getCardHolder(String tk1) {
        if (tk1 != null) {
            int bIdx = tk1.indexOf("^");
            int lIdx = tk1.lastIndexOf("^");
            if (bIdx >= 0 && lIdx >= 0) {
                return tk1.substring(bIdx + 1, lIdx).trim();
            }
        }
        return null;
    }
}
